#ifndef xpack_macro_xcheck_null
#define xpack_macro_xcheck_null
#pragma push_macro("xuser")
#undef  xuser
#define xuser mixc::macro_xcheck_null::inc
#include"macro/xlink.hpp"
#include"define/nullref.hpp"
#pragma pop_macro("xuser")

/*
// 简要用法：
// 用于检查成员参数，以及成员参数的成员参数...，是否为 nullptr
// 如果不为 nullptr 则返回当前字段的指针
#define xuser mixc::powerful_cat::inc
#include"macro/xcheck_null.hpp"
#include"macro/xmodify.hpp"
#include"definer/nullref.hpp"

struct ax;
struct bx{
    ax * the_ax;
};

struct ax{
    ax * the_ax;
    bx * the_bx;
};

void foo(ax * arg0, ax & arg1, ax * & arg2){
    using namespace xuser;

    // 需要一级一级约束
    if (ax * param = xcheck_null(arg0, ->the_ax, ->the_bx, ->the_ax); param == nullptr){
        // handle error...
    }



    // 由于 arg1 是引用，一般假定它为不 nullptr
    if (ax * param = xcheck_null(arg1->the_ax, ->the_bx, ->the_ax); param == nullptr){
        // handle error...
    }

    // 当然如果严谨一点，也可以这样
    if (arg1 == nullref){
        // handle...
    }
    else if (ax * param = xcheck_null(arg1.the_ax, ->the_bx, ->the_ax); param == nullptr){
        //                                ^ 注意这里是点

        // 不建议这么做   xcheck_null(& arg1, ->the_ax, ->the_bx, ->the_ax);
        // 因为大部分编译会认为引用不可能为 nullref，所以部分代码会被优化掉，
        // 如果 arg1 为 nullref，这种方式可能导致运行时错误
        // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

        // handle error...
    }



    // arg2 是个指针引用，代表还是一个指针
    // 但它类似于 ax ** 二级指针
    // 所以严谨的做法如下
    if (arg2 == nullref){
        // handle error...
    }
    else if (ax * param = xcheck_null(arg1, ->the_ax, ->the_bx, ->the_ax); param == nullptr){
        //                                  ^^ 注意这里是指向运算符
        // handle error...
    }
}
*/

#define __xcheck_null_core__(A00,A01,A02,A03,A04,A05,A06,A07,A08,A09,A10,A11,A12,A13,A14,A15,...) \
(([&]() -> decltype(auto) { \
    using __target_t = decltype(A00 A01 A02 A03 A04 A05 A06 A07 A08 A09 A10 A11 A12 A13 A14 A15 ); \
    if (auto const & __00 =      A00; __00 == nullptr) return __target_t(nullptr); else \
    if (auto const & __01 = __00 A01; __01 == nullptr) return __target_t(nullptr); else \
    if (auto const & __02 = __01 A02; __02 == nullptr) return __target_t(nullptr); else \
    if (auto const & __03 = __02 A03; __03 == nullptr) return __target_t(nullptr); else \
    if (auto const & __04 = __03 A04; __04 == nullptr) return __target_t(nullptr); else \
    if (auto const & __05 = __04 A05; __05 == nullptr) return __target_t(nullptr); else \
    if (auto const & __06 = __05 A06; __06 == nullptr) return __target_t(nullptr); else \
    if (auto const & __07 = __06 A07; __07 == nullptr) return __target_t(nullptr); else \
    if (auto const & __08 = __07 A08; __08 == nullptr) return __target_t(nullptr); else \
    if (auto const & __09 = __08 A09; __09 == nullptr) return __target_t(nullptr); else \
    if (auto const & __10 = __09 A10; __10 == nullptr) return __target_t(nullptr); else \
    if (auto const & __11 = __10 A11; __11 == nullptr) return __target_t(nullptr); else \
    if (auto const & __12 = __11 A12; __12 == nullptr) return __target_t(nullptr); else \
    if (auto const & __13 = __12 A13; __13 == nullptr) return __target_t(nullptr); else \
    if (auto const & __14 = __13 A14; __14 == nullptr) return __target_t(nullptr); else \
    if (auto const & __15 = __14 A15; __15 == nullptr) return __target_t(nullptr); else \
        return (__target_t)__15; \
})())

#define xcheck_null(...)        xlink(__xcheck_null_, core__(__VA_ARGS__,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,))

/*

#define xuser mixc::powerful_cat
#include"io/tty.hpp"
#include"mixc.hpp"

// 代码生成
// 只要修改这个参数就可以改变链式级数
uxx max_level = 16;

xinit(xuser::the_main){
   auto gen_line = [](uxx level, asciis pad = " ") {
       for(uxx i = 0; i < level; i++) {
           xuser::tty.write(
               "A\v\v", xuser::v{ i }.r(2, '0'), pad
           );
       }
   };

   xuser::tty.write("#define __xcheck_null_core__(");
   gen_line(max_level, ",");
   xuser::tty.write_line("...) \\");
   xuser::tty.write_line("(([&]() -> decltype(auto) { \\");
   xuser::tty.write("    using __target_t = decltype(");
   gen_line(max_level);
   xuser::tty.write_line("); \\");
   xuser::tty.write_line("    if (auto const & __00 =      A00; __00 == nullptr) return __target_t(nullptr); else \\");

   for(uxx i = 1; i < max_level; i++){
       xuser::tty.write_line("    if (auto const & __\v = __\v A\v; __\v == nullptr) return __target_t(nullptr); else \\", 
           xuser::v{i + 0}.r(2, '0'), 
           xuser::v{i - 1}.r(2, '0'), 
           xuser::v{i + 0}.r(2, '0'),
           xuser::v{i + 0}.r(2, '0')
       );
   }

   xuser::tty.write_line("        return (__target_t)__\v; \\", xuser::v{ max_level - 1 }.r(2, '0'));
   xuser::tty.write_line("})())");
};

*/

#endif
